#!/usr/bin/python
#
# Copyright 2010 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""app.py test module. These tests are run from ccfa_test.py."""

# Cruise Control for AppEngine
import app
import base_test


class AppTest(base_test.CruiseControlTest):
    """Tests app.py functionality, specifically:
         * url mappings
         * default response statuses
    """
    # Test request path to handler mapping.
    TEST_MAP = [
        # Index/default requests
        ('/', app.index.Index),
        ('/index', app.index.Index),
        ('/index/asdf', app.pages.Page),
        ('/index.html', app.index.Index),

        # Date requests
        ('/2010', app.posts.Date),
        ('/2010/', app.posts.Date),
        ('/2010/asdf', app.pages.Page),
        ('/2010/01', app.posts.Date),
        ('/2010/01/', app.posts.Date),
        ('/2010/01/asdf', app.pages.Page),
        ('/2010/01/18', app.posts.Date),
        ('/2010/01/18/', app.posts.Date),
        ('/2010/01/18/asdf', app.posts.Post),

        # Admin requests
        ('/admin', app.admin.Post),
        ('/admin/', app.admin.Post),
        ('/admin/asdf', app.pages.Page),
        ('/admin/links', app.admin.Links),
        ('/admin/links/', app.admin.Links),
        ('/admin/links/asdf', app.pages.Page),
        ('/admin/pages', app.admin.Pages),
        ('/admin/pages/', app.admin.Pages),
        ('/admin/pages/asdf', app.pages.Page),
        ('/admin/post', app.admin.Post),
        ('/admin/post/', app.admin.Post),
        ('/admin/post/asdf', app.pages.Page),
        ('/admin/comments', app.admin.Comments),
        ('/admin/comments/', app.admin.Comments),
        ('/admin/comments/asdf', app.pages.Page),
        ('/admin/settings', app.admin.Settings),
        ('/admin/settings/', app.admin.Settings),
        ('/admin/settings/asdf', app.pages.Page),
        ('/admin/import', app.admin.ImportFeed),
        ('/admin/import/', app.admin.ImportFeed),
        ('/admin/import/asdf', app.pages.Page),

        # CSS template requests
        ('/templates/asdf.css', app.templates.Css),

        # Image template requests
        ('/templates/asdf.png', app.templates.Img),
        ('/templates/asdf.gif', app.templates.Img),
        ('/templates/asdf.jpeg', app.templates.Img),
        ('/templates/asdf.jpg', app.templates.Img),

        # Javascript template requests
        ('/templates/asdf.js', app.templates.Js),

        # Search requests
        ('/search', app.search.Search),
        ('/search.html', app.search.Search),

        # Sitemap requests
        ('/sitemap', app.sitemap.SitemapHTML),
        ('/sitemap/', app.sitemap.SitemapHTML),
        ('/sitemap/asdf', app.pages.Page),
        ('/sitemap.html', app.sitemap.SitemapHTML),
        ('/sitemap.xml', app.sitemap.SitemapXML),
        ('/sitemap.rss', app.sitemap.SitemapRSS),
        
        # Page and 404 requests
        ('/asdf-page', app.pages.Page)
    ]
    
    def test_app_handler_mapping(self):
        """Test that our URL mapping is what we expect it to be."""
        self.app(self.wsgi_request(), self.mock_start_response.start_response)
        number_of_matches = 0
        for request_pattern, handler_class in AppTest.TEST_MAP:
            for regex, app_handler in self.app._url_mapping:
                match = regex.match(request_pattern)
                if not match:
                    continue
                number_of_matches += 1
                self.assertEqual(handler_class.__name__, app_handler.__name__)
                # webapp.WSGIApplication uses the first matched pattern, so we
                # also break as soon as we get a match.
                break
        
        self.assertEqual(number_of_matches, len(AppTest.TEST_MAP))
    
    def test_return_status(self):
        """Test to see that we get the response status we expect."""
        for request_pattern, handler_class in AppTest.TEST_MAP:
            path = {'PATH_INFO': request_pattern}
            self.app(self.wsgi_request(path),
                     self.mock_start_response.start_response)
            
            # Because we do not have any pages or Posts written to the
            # datastore, all calls to Page or Post will be 404.
            if request_pattern in ['/admin', '/admin/']:
                expected_status = 302
            elif request_pattern.startswith('/templates/'):
                expected_status = 404
            elif isinstance(handler_class(), (app.pages.Page,
                                              app.posts.Post)):
                expected_status = 404
            else:
                expected_status = 200
            self.assertEqual(self.mock_start_response.status, expected_status)